Skip to content

fix(discovery): resolve all native user-scope surfaces from the agent directory (#4769) - #4784

Open
Yeachan-Heo wants to merge 1 commit into
devfrom
fix/issue-4769-user-scope
Open

fix(discovery): resolve all native user-scope surfaces from the agent directory (#4769)#4784
Yeachan-Heo wants to merge 1 commit into
devfrom
fix/issue-4769-user-scope

Conversation

@Yeachan-Heo

@Yeachan-Heo Yeachan-Heo commented Aug 20, 2026

Copy link
Copy Markdown
Owner

What

Native user-scope discovery resolves native user surfaces from the selected agent directory with session-local policy authority.

Exact-head evidence

  • Head: e36e1048e26f8613584c94ce76de36bfc3451eed
  • Base: d06a42e53a9d6363d152a88c8168b5d6b2ab345e
  • Descriptor-relative native skill writes reject symlink and hard-link aliases before mutating SKILL.md.
  • Native secure-write regression suite passes (2/0).
gajae.pr-review-verdict.v1 needs-human sha256:c70dda2010f106b2561984658135033541dc9a039214bbf3632a6c53e4a5b9ff reviewer:human reviewer-id:pending-independent-review evidence:exact-head-hard-link-contained-skill-write


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f0ccee410

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

*/
function resolveUserAgentDir(ctx: LoadContext): string {
return ctx.userAgentDir ?? getAgentDir();
return path.resolve(ctx.userAgentDir ?? getAgentDir());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Thread the session agent directory into startup discovery

When createAgentSession({ agentDir }) selects a profile different from the process-wide getAgentDir(), this fallback still selects the process-wide profile because sdk/session.ts invokes loadSkills, rule discovery, and context-file discovery with only cwd, while the system-prompt loaders also expose no agentDir option. The session can therefore omit the requested profile's skills/instructions and inject SYSTEM.md, RULES.md, AGENTS.md, or skills from another profile; pass the resolved session agentDir through all capability-based startup readers rather than relying on this fallback.

Useful? React with 👍 / 👎.

name: string,
policy?: SkillsSettings,
home = getRuntimeHome(),
agentDir = getAgentDir(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass the session profile when resolving a discovered skill

For a session whose explicit agentDir differs from the process-wide directory, SkillDiscoveryTool now advertises skills from the session profile, but SkillTool still calls findRuntimeSkillByName(this.#session.cwd, requestedName, policy) without this new argument. If the skill is not already in the startup snapshot—for example, it was installed during the session—the subsequent invocation searches the global profile and reports the advertised skill as unavailable; thread getSessionAgentDir() into this lookup.

Useful? React with 👍 / 👎.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Verification evidence from the originating issue lane (same 22-file change set, original head 8f0ccee410, base 343067ab8f), for the reviewer at this exact head. Exact-diff digest computed with the same command CI uses (git diff --binary --full-index --no-ext-diff <base>...<head>):

  • base 343067ab8f → head 8f0ccee410: af5536cc3c6848605d77cc68ed43177e04c5111429af16796625c3974f157ff9
  • The reviewer at this head must recompute against this PR's declared base; do not reuse the head SHA — the template's sha256 field is the base...head diff digest, not a commit SHA.

Negative control (assertions are not environment-dependent)

Reverting only the source diff (tests kept) makes 6/7 of test/issue-4769-user-scope-agent-dir.test.ts fail on the old contract — and the old reader leaks the real machine's bundled workflow skills into exact-list assertions (["autoresearch","deep-interview","ralplan","ultragoal","writer-skill"] instead of the migrated skill), which is the product bug itself, not a harness artifact. In CI the same assertions fail as [].

Pre-existing local red, proven unrelated (identical with the diff stashed)

  • runtime-mcp/mcp-autoload-precedence.test.ts — 5 fails on this dev machine both with and without the change: the real ~/.gjc/plugins/installed_plugins.json installs hello-plugin@test-marketplace, whose .mcp.json contributes hello-plugin:test-server to every loadAllMCPConfigs call. getPluginsDir() is untouched by this diff. Not reproducible in CI.
  • issue-4508-cross-convention-fixture.test.ts — intermittent MCP-spawn timing flake; observed 1/6 failures on pristine dev (no diff) as well.

Fail-closed confirmations

Local suites at the original head (all green)

discovery/ (200 pass incl. the two new files), skills.test.ts, skill-management.test.ts, migrate-cli / -action-planner / -import / -schema-matrix / redteam, sdk-skills.test.ts, skill-hook-agent-dir-trust.test.ts, native-skill-hook-cache.test.ts, customization-extensions.test.ts, customization-dashboard.test.ts, issue-4508; bun --cwd=packages/coding-agent run check, check:schemas, check-visible-definitions, verify-g002-gates, rebrand-inventory --strict, default-gjc-definitions.test.ts.

Consolidation audit (no duplicate-lane drift)

This change set supersedes and fully contains the gajae-code-issue-4767-remaining lane: its unique pieces — user AGENTS.md following the resolved agent dir, the getConfigDirs() fold (settings/rules/hooks/prompts/extensions user scope), agentDir threading in tools/skill-discovery.ts + cli/skills-cli.ts, and test/discovery/builtin-user-agent-dir.test.ts (five-surface loadCapability coverage + malformed project config.yml not hiding a valid profile config) — are all in this diff. That worktree is marked superseded; no PR was opened from it.


Issue-lane handoff (issue #4769 → this PR): ownership of mutation/rebase/review/merge is with project-pr-4784-current. The issue lane holds for closure verification only.

Yeachan-Heo pushed a commit that referenced this pull request Aug 20, 2026
Keep terminal safety-stop authority exclusive to first-party adapter parse sites and sanitize the trailing completion path before managed-shell rebuilding. Public AI consumers can verify or transfer existing provenance but cannot mint it from message data or structural signals.

Fixes the two P1 review findings on #4777.

Lore-id: 4777-p1-provenance

Constraint: custom provider streams must remain fallback-eligible unless adapter provenance is authenticated

Constraint: user cancellation and non-error completion must never become provider safety stops

Rejected: public mint helper | arbitrary consumers could forge allowlisted terminal authority

Confidence: high

Scope-risk: regression-risk

Reversibility: revert-commit

Tested: focused provider, managed-attempt, session-retry, and provider-safety e2e suites

Not-tested: full CI after sibling #4784 merges
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

CI triage for Affected path validation / test:packages/coding-agent/test/tools/skill-discovery.test.ts (7 fails) — pre-existing suite isolation gap, not a #4784 regression, but the suite's expectation is stale under the new contract and does need an update in this PR.

Evidence

I reproduced locally on both the pristine pre-change base 343067ab8f (worktree, same lockfile) and this PR's change set: after removing one machine-specific artifact (writer-skill, a skill my own earlier local verification had written into the real ~/.gjc/agent/skills), the failure sets are byte-identical on both trees:

(fail) discovers user runtime skills from ~/.gjc/skills
(fail) does not classify home .gjc skills as project skills while walking up
(fail) discovers canonical and legacy user roots in native precedence order
(fail) uses the default and PI_CONFIG_DIR canonical user roots
(fail) applies policy before realpath/name dedup, then query, sort, and limit
(fail) applies source enable flags and skill filters to discovery and invocation
(fail) applies runtime precedence: project .gjc beats user, convention copies stay import candidates

(diff of sorted failure lists → identical. Two more local-only fails — advertises project .claude/skills…, diagnoses invalid frontmatter… — were caused solely by that stray real-home writer-skill and disappear once it is removed.)

Why it fails

These tests isolate the user scope by setting only process.env.HOME = <temp home> and expect the home-relative legacy roots under that temp home to be scanned. Since the trusted-home provenance rework (d9fabc8f5a), os/HOME swapping does not reach discovery — and after #4784 the user scope is the agent directory, so HOME alone never steers it. On my machine they fail by reading the real agent dir; in CI they fail as []. Either way the suite's isolation mechanism predates both hardenings.

The repair the PR lane should apply (mechanical, same pattern as the suites already updated in this PR)

In each affected test, after process.env.HOME = home add the agent-dir isolation the contract now defines:

const originalAgentDir = getAgentDir();
setAgentDir(path.join(home, ".gjc", "agent"));
// … finally: setAgentDir(originalAgentDir)

Two tests need slightly more because they deliberately set GJC_CODING_AGENT_DIR/PI_CODING_AGENT_DIR to decoy dirs and assert they are ignored for the home scan (discovers canonical and legacy user roots…, and the config-dir variants inside uses the default and PI_CONFIG_DIR canonical user roots):

  • discovers canonical and legacy user roots in native precedence order sets GJC_CODING_AGENT_DIR=<home>/.decoy-agent and expects the home-canonical + legacy roots to be scanned. Under the new contract the process-wide agent dir is the user scope, so the decoy wins by design. The test's intent ("an absolute-looking GJC_CONFIG_DIR is joined beneath home; decoy roots are not scanned") is about the legacy home-relative roots, which still exist in the default profile — so it should isolate with setAgentDir(path.join(home, ".gjc", "agent")) in addition to the env decoys, and keep asserting the decoy agent dir contributes nothing.
  • uses the default and PI_CONFIG_DIR canonical user roots asserts <configDir>/agent/skills under GJC_CONFIG_DIR/PI_CONFIG_DIR — those are SOURCE_PATHS.native.userBase/userAgent compositions from home, which remain in getUserSkillScanDirs for the default profile. Same fix: isolate the agent dir to the home-canonical path.

gjc config dir (the contract's single seam) then holds for every case, and none of these tests' real assertions (precedence order, decoy rejection, boundary between project walk-up and user scope) change meaning.

Two template/contract failures (also for the PR lane)

PR contract bootstrap and Validate exact-head PR contract fail because the body I published has (a) no risk-classification checkbox and (b) a placeholder verdict line. Digest for the verdict, computed the way CI does (git diff --binary --full-index --no-ext-diff <base>...<head>): for original base 343067ab8f → head 8f0ccee410 it is af5536cc3c6848605d77cc68ed43177e04c5111429af16796625c3974f157ff9; recompute against the PR's current base/head before writing it. Risk classification: this change alters the user-scope/config/trust discovery contract — regression-risk is the honest class unless repo doctrine's exact-classification table says otherwise (owner's call).

cc @Yeachan-Heo @probepark @snowykr

@Yeachan-Heo
Yeachan-Heo force-pushed the fix/issue-4769-user-scope branch from 8f0ccee to b72820c Compare August 20, 2026 21:59
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact-head human gate for PR #4784:

  • Head: b72820cb996af0ed19bd17a43bef6342b807b04a
  • Current dev: ba7096f72184929070f295019e8173c41ab1e468
  • Diff digest: sha256:bfc7c436a0462f5d03b75b422e8453df8411e76e988d815de776b07b22322249
  • Risk: high-risk

The exact remote #4784 delta was transplanted byte-for-byte, and the follow-up fixes session home/agent-dir injection through actual tool construction so skill_discovery and skill honor profile scope. Please have probepark or snowykr review and approve this exact head after the full CI run. The PR remains needs-human until an authenticated exact-head approval is recorded.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b72820cb99

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

getActiveSkillPhase: () => session?.getActiveSkillPhase(),
getDeepInterviewAskStage: () => session?.getDeepInterviewAskStage(),
getHindsightSessionState: () => session?.getHindsightSessionState(),
getSessionAgentDir: () => agentDir,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive the tool profile from injected settings

When createAgentSession receives profile-scoped settings without a separate agentDir, this accessor returns the process-wide directory captured in agentDir rather than settings.getAgentDir(). This is the path used by canonical subagents: task/executor.ts passes settings: subagentSettings but no agentDir. Consequently, their skill_discovery and runtime skill fallback scan the default profile, omitting the parent's profile skills and potentially advertising skills from another profile. Use the injected settings directory when options.agentDir is absent.

Useful? React with 👍 / 👎.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

@probepark @snowykr please review exact head b72820cb996af0ed19bd17a43bef6342b807b04a for the high-risk user-scope contract. The independent approval must target this exact commit; the final verdict and full CI gate remain blocked until one of you approves.

@snowykr snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict

CHANGES_REQUESTED

Summary

The five-axis review completed against the exact head and identified 3 actionable issues, led by Custom-home runtime discovery ignores the supplied home and Honor the supplied home when resolving the default agent directory. These findings require changes before approval.

Findings / Required Changes

  1. [P1] Custom-home runtime discovery ignores the supplied home.
    Reference: packages/coding-agent/src/extensibility/runtime-skill-discovery.ts:349-350
    When home is provided without agentDir, discovery defaults to process-global getAgentDir() instead of deriving the default agent directory from that home, so injected/test homes and SDK callers can miss their user skills. Derive the default agent directory from the supplied home or preserve the prior home-relative behavior.
  2. [P1] Honor the supplied home when resolving the default agent directory.
    Reference: packages/coding-agent/src/extensibility/runtime-skill-discovery.ts:349-356
    When callers provide options.home but omit agentDir, discovery falls back to process-global getAgentDir() rather than &lt;home&gt;/.gjc/agent; custom-home callers can therefore read another profile's skills, and concurrent profile changes can select the wrong scope. Derive the default agent directory from the supplied home or require callers to pass both values consistently.
  3. [P2] Document configurable user paths consistently.
    Reference: docs/customization.md:45-47
    The authority contract and skill documentation identify the configurable agent directory, but the MCP and Hook rows still present ~/.gjc/agent as universally authoritative. Update these rows to use <agentDir> with the default path noted, matching the agent-directory profile behavior.

CI / Verification

  • Reviewed the exact remote head: b72820cb996af0ed19bd17a43bef6342b807b04a.
  • CI summary: 34 passing, 3 failing, 11 pending/cancelled/skipped.
  • Failing checks: Validate exact-head PR contract, Validate exact-head PR contract, PR contract bootstrap.
  • Repository policy permits review before all gating checks pass; the current non-passing checks are recorded above and do not establish that checks passed.

Axis Coverage

Axis Verdict Coverage
A1. Intent / Policy / Contract APPROVED Agent-directory profile isolation and legacy default-profile compatibility are established without an actionable API boundary defect.
A2. Architecture / Correctness / Failure CHANGES_REQUESTED Runtime skill discovery correctly propagates explicit agent directories, but omitted agentDir with a supplied home can cross profile boundaries; no additional concurrency defect was established.
A3. Security / Privacy / Trust APPROVED Security and privacy risk from agent-directory skill and configuration discovery was reviewed; no actionable regression was established.
A4. Verification / Tests / CI CHANGES_REQUESTED A4 review establishes passing affected tests and CI, with one observable custom-home discovery regression and unresolved PR-contract validation.
A5. Context / Compatibility / Platform CHANGES_REQUESTED A1/A5 integration and platform documentation is mostly aligned, but MCP and Hook path references remain stale for configured agent-directory profiles.

Limitations

  • PR contract checks failed, so merge-contract compliance is not established; affected validation and tests passed.
  • PR contract checks failed, but ci_summary exposes no failure reason, so exact contract noncompliance cannot be assessed.
  • PR contract checks failed, so contract validation is not treated as passing evidence.
  • Windows native and darwin-arm64 platform jobs were skipped, so platform behavior on those targets was not verified by CI.

@nahyeongjin1

Copy link
Copy Markdown
Contributor

#4768 author here (the MCP half of #4769's parent). This carries the remaining five surfaces the way the review asked, and the getUserSkillScanDirs(home, userAgentDir) split — profile dir when overridden, home legacy roots otherwise — is the right shape.

One review item from #4768 is still open, and this PR is the last cheap moment for it. @probepark's approving review there ended with:

minor — make the field required. builtin.ts:58-59 falls back to global getAgentDir() when ctx.userAgentDir is absent, so the provider is not strictly context-pure. Making the field required removes the silent fallback and forces every context builder to resolve it once, which is the property that made this approach correct in the first place.

This PR keeps userAgentDir?: string and turns the fallback into path.resolve(ctx.userAgentDir ?? getAgentDir()) (capability/types.ts:32, discovery/builtin.ts:193-195). After this lands, all six native user-scope surfaces route through resolveUserAgentDir(ctx), so the fallback becomes the one remaining path by which a context builder that forgets the field silently gets process-global state — which is exactly the failure class #4767 was: two resolvers, one scope, disagreeing only under a profile.

I measured the cost on your exact head b72820cb9 (flip to userAgentDir: string, tsc -p packages/coding-agent): 24 sites, 8 files.

file sites already rewritten by this PR
src/extensibility/runtime-skill-discovery.ts 8 yes
src/extensibility/skill-management.ts 6 yes
src/extensibility/skills.ts 2 yes
src/cli/customize-doctor.ts 2 no
test/discovery/agents-monorepo-skills.test.ts 3 no
test/discovery/{monorepo-skills,agents-md,pi-config-dir}.test.ts 3 no

16 of 24 are inside files this PR already rewrites, and the 8 others are mechanical — customize-doctor's two contexts feed foreign-convention inspection and skills.customDirectories scanning, so they never consume the native user scope and can pass the resolved value without changing behavior. Doing it here costs a handful of lines; doing it later means re-touching every file this PR just migrated.

Not blocking from me — I do not own this lane and I am not the reviewer of record. But the request was explicit and the mechanism is being finalized in this diff, so it should be a deliberate accept-or-decline rather than something that falls off the edge of two PRs.

(For the record on the other half: #4768's docs deliberately claimed only "discovery, gjc mcp add, and the disabledServers denylist" move with a profile — this PR is what makes the broader claim true, and docs/customization.md / docs/skills.md in your diff are updated accordingly.)

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Reviewer follow-up is complete at exact head 92d7c4f38ea1fac7dcf2901551d63d7a16289606.

Addressed snowykr's three findings:

  1. options.home without agentDir now derives <home>/<configDirName>/agent through one resolver.
  2. Added concurrent custom-profile isolation coverage.
  3. Updated customization MCP and Hook rows to <agentDir> with the default path.

Please perform a fresh exact-head review and approve if satisfied. The PR remains needs-human until an authenticated approval is recorded.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92d7c4f38e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

policy?: SkillManagementPolicy;
}): Promise<ManagedSkillRecord[]> {
const home = options.home ?? getRuntimeHome();
const agentDir = options.agentDir ?? getAgentDir();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive management scope from an injected home

When callers supply the existing home override without the new agentDir option, this now scans the process-wide profile instead of <home>/.gjc/agent; exported SDK consumers and loadCustomizationInventory tests using an isolated home can therefore omit that home's user skills and expose skills from the real profile. Preserve the prior home-only behavior by deriving the default agent directory from an explicitly supplied home, as discoverRuntimeSkills now does.

Useful? React with 👍 / 👎.

@probepark probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First review at exact head 92d7c4f3merge blocked. This is real progress on #4767 and I measured it fixing a suite that is currently red on dev, but the session-scoped call sites were not threaded and the test that appears to cover that performs the missing step itself.

measured benefit, not just claimed

I ran the currently-red suites against this head with a real install and natives built:

suite on dev ba7096f7 on this head
skills.test.ts 31 pass / 5 fail 36 pass / 0 fail
gjc-plugin-no-surface.test.ts 3 / 1 3 / 1
coordinator-mcp/stop-session.test.ts 5 / 6 5 / 6

So this genuinely closes the skills half of the ambient-home problem. The other two remain red and are not this PR's job.

the trust boundary holds

I checked this first, because a discovery-path change is where a checkout could gain authority. loadCapability selects an explicit caller agentDir or trusted getAgentDir() (capability/index.ts:239-242); project .env overrides are rejected by trustedValue (utils/src/dirs.ts:222-230, :429-432); and Settings.agentDir is constructor state rather than config.yml data (config/settings.ts:544-547). No project-level setting gains a say.

major — session-scoped profiles write to one place and read from another

sdk/session.ts:1288 captures the session's authority:

const agentDir = options.agentDir ?? getDefaultAgentDir();

Startup discovery does not use it (:1408-1411):

: logger.time("discoverContextFiles", loadContextFilesResultInternal, { cwd });

Only cwd. So a session created with an explicit agentDir writes settings and skills under that profile while loading skills, RULES.md, AGENTS.md, SYSTEM.md and the shared native capability surfaces through the process-wide fallback. That is the same write/read divergence #4767 is about, surviving for session scope precisely because this PR made the readers consume LoadContext.userAgentDir without updating the session call sites that must supply it.

And the test cannot see it. test/issue-4769-user-scope-agent-dir.test.ts:144-169 calls setAgentDir(profile) before loadSkills, which makes the global resolution agree with the session profile — so the divergence is masked by the setup. That is a test performing the missing production step itself: it proves the mechanism can work, not that the session path uses it.

The regression that would catch it: createAgentSession({ agentDir }) while the global getAgentDir() points elsewhere, asserting every startup reader resolves to the session profile.

coverage gaps worth closing with it

Positive pins exist for config, SYSTEM.md, skills, RULES.md and AGENTS.md (test/discovery/builtin-user-agent-dir.test.ts:65-100), and old-path negative controls exist for SYSTEM.md, RULES.md and skills (issue-4769-user-scope-agent-dir.test.ts:76-113) — but not for AGENTS.md, config.yml, or the shared getConfigDirs consumers. Decoys for every migrated surface would make the migration self-guarding.

pre-existing caveat, not attributed here

capability/fs.ts:11-38 collapses every readFile/readDirEntries error into cached absence, and discovery/builtin.ts:67-92 treats an unreadable profile as empty. So a permissions error on a user profile reads as "no configuration" rather than surfacing. Untouched by this PR, worth its own change.

Reviewed by @probepark — method: verified the trust boundary before assessing the fix, measured the currently-red suites against this head with a real install rather than my symlinked worktree, then traced the captured session agentDir into the startup discovery calls and checked what the covering test sets up before asserting.

gajae.pr-review-verdict.v1 merge-blocked sha256:ebfb02cc7ff17126869d7e938dc3719533272a0a7463385bd8186200b3e730d0 reviewer:human reviewer-id:probepark evidence:exact-head-92d7c4f3-fixes-skills-suite-36-0-but-session-scoped-agentdir-is-captured-and-not-threaded-into-startup-discovery

Yeachan-Heo pushed a commit that referenced this pull request Aug 20, 2026
Keep terminal safety-stop authority exclusive to first-party adapter parse sites and sanitize the trailing completion path before managed-shell rebuilding. Public AI consumers can verify or transfer existing provenance but cannot mint it from message data or structural signals.

Fixes the two P1 review findings on #4777.

Lore-id: 4777-p1-provenance

Constraint: custom provider streams must remain fallback-eligible unless adapter provenance is authenticated

Constraint: user cancellation and non-error completion must never become provider safety stops

Rejected: public mint helper | arbitrary consumers could forge allowlisted terminal authority

Confidence: high

Scope-risk: regression-risk

Reversibility: revert-commit

Tested: focused provider, managed-attempt, session-retry, and provider-safety e2e suites

Not-tested: full CI after sibling #4784 merges

@snowykr snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict

CHANGES_REQUESTED

Summary

The five-axis review completed against the exact head and identified 5 actionable issues, led by Ignored home override breaks skill-management API compatibility and Injected home is ignored for skill-management user paths. These findings require changes before approval.

Findings / Required Changes

  1. [P1] Ignored home override breaks skill-management API compatibility.
    Reference: packages/coding-agent/src/extensibility/skill-management.ts:145
    resolveNativeSkillScopeDir previously used its third home argument for default user writes, but it is now ignored and user writes use the process-wide agent directory. Preserve the established home-based behavior when agentDir is omitted, while allowing explicit agentDir profiles.
  2. [P1] Injected home is ignored for skill-management user paths.
    Reference: packages/coding-agent/src/extensibility/skill-management.ts:145-150,176
    resolveNativeSkillScopeDir and listNativeSkillsForManagement default agentDir to process-global getAgentDir() even when home is explicitly supplied. User writes/listing for an injected profile can target or read another profile, especially concurrently. Derive the default agent directory from the injected home, or require/pass agentDir consistently, and add isolation tests for omitted agentDir.
  3. [P1] Injected profile home can expose global user skills.
    Reference: packages/coding-agent/src/extensibility/skill-management.ts:179
    listNativeSkillsForManagement derives agentDir from process-global getAgentDir() when home is injected but agentDir is omitted, potentially scanning another profile's skills. Derive the default agent directory from the injected home or require an explicit agentDir.
  4. [P1] Injected-home skill writes use the process-global profile.
    Reference: packages/coding-agent/src/extensibility/skill-management.ts:145-151
    resolveNativeSkillScopeDir ignores its supplied home and defaults agentDir to getAgentDir(), so writeNativeSkill({home}) can write outside the injected profile while discovery resolves that profile’s agent directory; derive the default agent directory from the supplied home or require and consistently pass agentDir.
  5. [P1] Missing ToolSession accessor.
    Reference: packages/coding-agent/src/tools/skill.ts:133
    The skill tool calls getSessionAgentDir(), but ToolSession does not declare that member. Add the optional accessor to ToolSession (or remove the call) and ensure session construction satisfies the interface.

CI / Verification

  • Reviewed the exact remote head: 92d7c4f38ea1fac7dcf2901551d63d7a16289606.
  • CI summary: 34 passing, 2 failing, 12 pending/cancelled/skipped.
  • Failing checks: Validate exact-head PR contract, PR contract bootstrap.
  • Repository policy permits review before all gating checks pass; the current non-passing checks are recorded above and do not establish that checks passed.

Axis Coverage

Axis Verdict Coverage
A1. Intent / Policy / Contract CHANGES_REQUESTED Profile-based skill discovery and writing are mostly aligned, but the session accessor contract and backward-compatible home override remain concrete API risks.
A2. Architecture / Correctness / Failure CHANGES_REQUESTED Correctness is mostly coherent, but injected-home skill-management calls can violate profile isolation and produce cross-profile results under concurrency.
A3. Security / Privacy / Trust CHANGES_REQUESTED Profile isolation is enforced in runtime discovery, but skill-management listing can cross profile boundaries when callers inject home without agentDir.
A4. Verification / Tests / CI APPROVED A4 review found passing affected tests and no established regression; CI contract failures remain an unresolved verification risk.
A5. Context / Compatibility / Platform CHANGES_REQUESTED Integration and platform review found a profile-isolation risk in the skill writer; documentation changes otherwise align the advertised agent-directory model.

Limitations

  • The PR contract and bootstrap CI checks are failed, so exact-head contract validation could not be established; affected-path tests and virtual integration validation succeeded.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Final fix-forward exact head is ready for a fresh review:

  • Head: 6ebd7b06ea0575640ad70a013c91a3c3b1b6a6be
  • Base: ba7096f72184929070f295019e8173c41ab1e468
  • Digest: sha256:403c9b5261085d363ff689ea325f30d7f63b8de786fe9294e52a1447b13a95f2

Addressed both reviewers' requested changes: actual session startup threading, home-relative skill-management list/write resolution with concurrent isolation, and negative decoys for AGENTS/config/shared config-directory consumers. Affected tests and coding-agent package check pass. Please review and approve this exact head if satisfied.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ebd7b06ea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

): Promise<ProjectContextFilesResult> {
const resolvedCwd = options.cwd ?? getProjectDir();
const result = await loadCapability(contextFileCapability.id, { cwd: resolvedCwd });
const result = await loadCapability(contextFileCapability.id, { cwd: resolvedCwd, agentDir: options.agentDir });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Forward the profile through discoverContextFiles

When an SDK embedder calls the exported discoverContextFiles(cwd, profileDir) while the process-wide getAgentDir() points elsewhere, sdk/session.ts still ignores its _agentDir argument and invokes loadContextFilesInternal with only cwd. Consequently this new option remains undefined and the helper reads the global profile's AGENTS.md instead of the requested profile's file. Although createAgentSession now forwards its profile correctly, the standalone SDK discovery helper needs to forward its second argument as well.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 2d4f27ff827624811533ed2a36df170b11396aa4 on base b88ee64a8f6104a1a036973fb15ffd209c05ea75. It fixes the exact review blocker by propagating the owning session settings through context/system-prompt, hooks, and slash-command capability discovery. Coding-agent check and focused tests pass (67/0). Please re-review this exact high-risk head; earlier review evidence is stale.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@Yeachan-Heo
Yeachan-Heo force-pushed the fix/issue-4769-user-scope branch from 2d4f27f to 0884d5d Compare August 23, 2026 06:02
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 0884d5d7b74187ac880183a95fdfc42b1349d07b on base b88ee64a8f6104a1a036973fb15ffd209c05ea75. Added same-cwd concurrent opposite-policy/close-order isolation coverage for the Settings-authority fix. Coding-agent check and the regression pass. Please exact-head re-review; prior evidence is stale.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo
Yeachan-Heo force-pushed the fix/issue-4769-user-scope branch from 0884d5d to 7bfc6ad Compare August 23, 2026 06:04
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 7bfc6ad3aab0abae118090979a2110fbc4bbb457 on base b88ee64a8f6104a1a036973fb15ffd209c05ea75. The final system-prompt settings propagation is included, so all identified session-scoped discovery paths now receive the owning settings authority. Please exact-head re-review; all prior review evidence is stale.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is a045a3f69508cd34d307180e8fa94c9edf408578 on base b88ee64a8f6104a1a036973fb15ffd209c05ea75. Native skills now also receive the owning session Settings during startup/rescope discovery. The current settings-authority delta is complete and tested (39/0); please exact-head re-review.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 1d084bc385626b302aceb86d81ab7d874241ecc9, rebased onto current dev fa4364695117fd9a44d6fd3a8a3ed8b2fe88f7c6. The changelog conflict retained both current-dev entries and the #4769 discovery entry. Prior evidence/reviews are stale; please exact-head re-review.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@snowykr snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict

CHANGES_REQUESTED

Summary

The five-axis review completed against the exact head and identified 4 actionable issues, led by Correct configured-agent write-path assertion and Removed ToolSession.home breaks existing SDK/tool integrations. These findings require changes before approval.

Findings / Required Changes

  1. [P1] Correct configured-agent write-path assertion.
    Reference: packages/coding-agent/test/skill-management.test.ts:123
    The test writes configured-skill but expects a receipt path ending in my-skill; update the expected path to configured-skill.
  2. [P1] Removed ToolSession.home breaks existing SDK/tool integrations.
    Reference: packages/coding-agent/src/tools/index.ts:237-238
    The public ToolSession interface no longer accepts the previously supported home field, so external session/tool implementations using it fail type-checking; retain a deprecated home alias or provide a compatibility migration before removing it.
  3. [P1] Validate native skill names before writing.
    Reference: packages/coding-agent/src/extensibility/skill-management.ts:280-282
    frontmatter.name is used directly in path.join, so values such as ../outside or nested separators can escape the selected skills directory. Reject path separators, . and .., and verify the resolved destination remains beneath the scope directory before mkdir/write.
  4. [P2] Skill-management public contract documents obsolete fixed paths.
    Reference: packages/coding-agent/src/extensibility/skill-management.ts:3-8
    The module-level API documentation still states global ~/.gjc/agent/skills as canonical despite agentDir profiles being supported; update the contract to describe the selected agent directory and default fallback.

CI / Verification

  • Reviewed the exact remote head: 1d084bc385626b302aceb86d81ab7d874241ecc9.
  • CI summary: 1 passing, 3 failing, 15 pending/cancelled/skipped.
  • Failing checks: Validate exact-head PR contract, Validate exact-head PR contract, PR contract bootstrap.
  • Repository policy permits review before all gating checks pass; the current non-passing checks are recorded above and do not establish that checks passed.

Axis Coverage

Axis Verdict Coverage
A1. Intent / Policy / Contract CHANGES_REQUESTED Agent-directory propagation is mostly coherent, but removing ToolSession.home creates a source compatibility break for external SDK/tool hosts.
A2. Architecture / Correctness / Failure CHANGES_REQUESTED Concurrency ordering is deterministic in the inspected discovery paths; native skill writes retain an actionable path traversal risk.
A3. Security / Privacy / Trust APPROVED Agent-directory isolation and user-scope discovery changes do not establish a security or privacy defect.
A4. Verification / Tests / CI CHANGES_REQUESTED A4 verification is incomplete in CI and includes one confirmed failing assertion in the added configured-agent-directory test.
A5. Context / Compatibility / Platform APPROVED Agent-directory profiles are consistently threaded through discovery, runtime loading, session startup, and documentation; CI verification remains incomplete.

Limitations

  • Failed PR contract checks and skipped platform/integration jobs prevent claiming CI-verified cross-platform behavior.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 472cb97c0a311370d7436f52dfe141092d764fcb on base fa4364695117fd9a44d6fd3a8a3ed8b2fe88f7c6. It fixes the current review blockers: ToolSession.home type compatibility, skill write traversal rejection with a regression test, and profile-aware skill-management contract docs. Please exact-head re-review; earlier evidence is stale.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

1 similar comment
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is ded195471d687faf8081e9193b056bc3d534c3d4 on base fa4364695117fd9a44d6fd3a8a3ed8b2fe88f7c6. Legacy ToolSession.home now retains behavioral compatibility as the runtime-skill fallback before getSessionHome(). Tool skill/discovery suites and coding-agent check pass. Please exact-head re-review.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 4ad86b71bedc13c1e77f282e468b9acda0767031 on base fa4364695117fd9a44d6fd3a8a3ed8b2fe88f7c6. It addresses the architect blockers: explicit parent profile propagation into delegated sessions and symlink-contained native skill writes, with focused regressions. Please exact-head re-review; prior review/CI evidence is stale.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 689ffa550c4ed571fac13d4aabed1205ffbc53c8 on base fa4364695117fd9a44d6fd3a8a3ed8b2fe88f7c6. It completes the architect's residual paths: isolated task parent-agent propagation and project skill-root symlink rejection. Focused regressions and coding-agent check pass. Please exact-head re-review.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@probepark probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delta review at exact head 689ffa55merge blocked.

Session-core/delegated Settings threading and static skill-write symlink/traversal defenses are fixed. Two HIGH compatibility/public-boundary defects remain:

  1. public SDK discoverContextFiles(cwd, agentDir) and buildSystemPrompt({agentDir}) cannot carry the owning Settings. They still fall back to cwd/global last-session policy, so same-cwd profiles can authorize/suppress each other's providers/extensions and context, including after close-order changes.
  2. the new deprecated ToolSession.home field is preferred over trusted getSessionHome(). A stale compatibility value can redirect home-relative custom skill discovery and exact invocation to another profile.

Thread Settings through both public SDK wrappers and test concurrent same-cwd profiles/close orders. Use getSessionHome?.() ?? home in skill discovery/invocation, with conflicting-value regressions.

Approved native precedence, protected names, chaining, delegated profile propagation, and static write containment otherwise remain intact.

Reviewed by @probepark — finite delta review from blocked 7a35fda9.

gajae.pr-review-verdict.v1 merge-blocked sha256:d60c13292f40b0f3f0895274177962267cbd28bbe61562804a98f135d0241360 reviewer:human reviewer-id:probepark evidence:exact-head-689ffa55-public-settings-and-trusted-home-authority-gaps

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact current head is 725682ea13237fe8c11b0434ccec8dbbfe41681b, rebased onto current dev d06a42e53a9d6363d152a88c8168b5d6b2ab345e. It adds descriptor-relative native O_NOFOLLOW skill writes and removes the path-based fallback. Native binding rebuild, skill-management regression suite, and coding-agent check pass. Please exact-head re-review; all pre-d06a evidence is stale.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact head 102f449cdf694183f2d0b17c442bcc1ff6000876 adds verified native descriptor-relative skill writes. The Rust secure-write tests pass (2/0), including missing-tree/overwrite and symlink refusal. Prior evidence is stale; exact-head CI and re-review are required.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@snowykr snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict

CHANGES_REQUESTED

Summary

The five-axis review completed against the exact head and identified 7 actionable issues, led by Concurrent skill writes can overwrite or interleave nondeterministically and Configured-agent skill test expects the wrong path. These findings require changes before approval.

Findings / Required Changes

  1. [P1] Concurrent skill writes can overwrite or interleave nondeterministically.
    Reference: crates/pi-natives/src/path_identity.rs:4467-4515
    Multiple writers can open the same SKILL.md, each validate and truncate it, then write without serialization or atomic replacement. Serialize per target or write a temporary descriptor and atomically replace it after validation.
  2. [P1] Configured-agent skill test expects the wrong path.
    Reference: packages/coding-agent/test/skill-management.test.ts:166-167
    The test writes configured-user but asserts a receipt path ending in my-skill; update the expected path to configured-skill so the configured-agent behavior can pass.
  3. [P1] User skill writes are unavailable on Windows.
    Reference: crates/pi-natives/src/path_identity.rs:8728-8734
    The Windows native implementation always returns unsupported_platform, while writeNativeSkill now requires this primitive and no longer has a compatible fallback; implement a reparse-safe Windows writer or explicitly preserve a supported cross-platform API contract.
  4. [P2] Configured skill test asserts the wrong effective name.
    Reference: packages/coding-agent/test/skill-management.test.ts:191
    The test writes frontmatter naming my-skill while requesting configured-skill, then expects a my-skill path. Update the fixture or expected path so the test verifies the intended contract.
  5. [P2] Configured-agent skill test expects the wrong skill name.
    Reference: packages/coding-agent/test/skill-management.test.ts:192-193
    The test writes configured-skill but asserts a path containing my-skill, so it fails independently of the implementation; assert the requested/effective configured-skill path.
  6. [P2] Document unsupported skill writes on Windows and non-Unix platforms.
    Reference: docs/skills.md:69-83
    The native writer explicitly returns unsupported_platform outside Unix, causing managed writes to fail closed, but the installation documentation presents the workflow without a platform caveat. Document this limitation and provide the supported manual-copy alternative.
  7. [P2] Skill writes block the JavaScript thread.
    Reference: packages/coding-agent/src/extensibility/skill-management.ts:318-326
    The synchronous native binding performs directory creation, truncation, and an unbounded content write inside the caller’s thread, so large content or slow storage can stall the event loop and concurrent sessions. Provide an async blocking-pool binding or enforce a bounded write path.

CI / Verification

  • Reviewed the exact remote head: 102f449cdf694183f2d0b17c442bcc1ff6000876.
  • CI summary: 1 passing, 2 failing, 15 pending/cancelled/skipped.
  • Failing checks: Validate exact-head PR contract, PR contract bootstrap.
  • Repository policy permits review before all gating checks pass; the current non-passing checks are recorded above and do not establish that checks passed.

Axis Coverage

Axis Verdict Coverage
A1. Intent / Policy / Contract CHANGES_REQUESTED Agent-directory propagation is broadly consistent, but Windows skill-write compatibility is not preserved and one compatibility test is internally inconsistent.
A2. Architecture / Correctness / Failure CHANGES_REQUESTED The new skill writer is not concurrency-safe and performs blocking filesystem work synchronously; other correctness risks were not established.
A3. Security / Privacy / Trust APPROVED No concrete security or privacy defect established; skill writes and profile-scoped discovery implement containment and isolation controls.
A4. Verification / Tests / CI CHANGES_REQUESTED A4 review established a deterministic failing test assertion; CI health remains limited by reported contract failures and skipped validation jobs.
A5. Context / Compatibility / Platform CHANGES_REQUESTED Agent-directory integration and skill documentation are mostly aligned, but a test contradiction and undocumented non-Unix write limitation leave compatibility risk.

Limitations

  • PR contract bootstrap failed and affected integration, native-build, Windows, and platform validation jobs were skipped; therefore those CI validations cannot establish cross-platform pass status.

Native capability readers and writers diverged whenever a session or SDK caller selected an agent-directory profile. Thread the resolved profile through every native discovery surface while preserving explicit-home SDK isolation and current session settings authority.\n\nLore-id: 4784-recovery\nConstraint: preserve current-dev #4840/#4841 session settings and cancellation behavior\nRejected: replay stale CI and release changes | outside the user-scope discovery boundary\nConfidence: high\nScope-risk: wide\nReversibility: revertible\nTested: focused native user-scope discovery suite; coding-agent type check\nNot-tested: PR-hosted CI
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Exact head e36e1048e26f8613584c94ce76de36bfc3451eed closes the native writer hard-link gap: existing SKILL.md descriptors must have link count one before truncation, with regression coverage. Native secure-write suite passes 2/0. Please exact-head re-review.


[repo owner's gaebal-gajae (clawdbot) 🦞]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants